package com.keyboardr.gamerater;

import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.ExecutionException;

import org.json.JSONArray;
import org.json.JSONException;

import android.app.ActionBar;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.AbsListView;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.Spinner;
import android.widget.TabHost;
import android.widget.TabHost.TabSpec;
import android.widget.ToggleButton;

public class RaterActivity extends FragmentActivity implements OnClickListener,
		GroupContainer {
	public static boolean isHolo = false;
	private static final String TAG = "RaterActivity";
	private ArrayList<Group> mGroups;
	private Group selectedGroup;
	private boolean ratingSort = true;
	private ArrayList<Player> sortedList;
	private boolean deserializationFault;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		if ((Build.VERSION.SDK_INT >= 11)
				&& (getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) > Configuration.SCREENLAYOUT_SIZE_NORMAL) {
			isHolo = true;
		}

		final SharedPreferences settings = getPreferences(MODE_PRIVATE);
		ProgressDialog progress = ProgressDialog.show(this, "",
				"Loading.  Please wait...", true);
		deserializationFault = false;
		AsyncTask<Void, Void, ArrayList<Group>> loadFile = new AsyncTask<Void, Void, ArrayList<Group>>() {

			@Override
			protected ArrayList<Group> doInBackground(Void... arg0) {

				JSONArray groups;
				ArrayList<Group> aList = null;
				try {
					groups = new JSONArray(settings.getString("groups", ""));
					Log.d(TAG,
							"loading "
									+ settings.getString("groups",
											"nothing saved"));
					aList = new ArrayList<Group>(groups.length());
					for (int i = 0; i < groups.length(); i++) {
						aList.add(new Group(groups.getJSONObject(i)));
					}
				} catch (JSONException e) {
					deserializationFault = true;
					e.printStackTrace();
				}
				return aList;
			}
		}.execute();

		Button groupSpinner = null;
		if (!isHolo) {
			ImageButton newPlayerButton = (ImageButton) findViewById(R.id.addPlayerButton);
			newPlayerButton.setOnClickListener(this);

			ToggleButton playerSortButton = (ToggleButton) findViewById(R.id.playerSortButton);
			playerSortButton.setOnClickListener(this);

			groupSpinner = (Button) findViewById(R.id.groupSpinner);
			groupSpinner.setOnClickListener(this);

			TabHost tabHost = (TabHost) findViewById(R.id.tabhost);
			tabHost.setup();

			TabSpec spec1 = tabHost.newTabSpec("Tab 1");
			spec1.setContent(R.id.tab1);
			spec1.setIndicator("Ratings");

			TabSpec spec2 = tabHost.newTabSpec("Tab 2");
			spec2.setContent(R.id.tab2);
			spec2.setIndicator("History");

			tabHost.addTab(spec1);
			tabHost.addTab(spec2);
		} else {
			if (getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
				groupSpinner = new GroupSpinner(this);
				groupSpinner.setId(R.id.groupSpinner);
				groupSpinner.setOnClickListener(this);
				getActionBar().setCustomView(groupSpinner);
				getActionBar().setDisplayOptions(
						ActionBar.DISPLAY_SHOW_CUSTOM
								+ ActionBar.DISPLAY_SHOW_HOME
								+ ActionBar.DISPLAY_SHOW_TITLE);
			}
		}

		Log.d(TAG, "line 124");
		try {
			mGroups = loadFile.get();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
		if (mGroups == null || mGroups.size() == 0 || deserializationFault) {
			mGroups = new ArrayList<Group>();
			mGroups.add(new Group("Default", false));
		}
		progress.dismiss();
		Log.d(TAG, "line 137");
		try {
			selectedGroup = mGroups.get(settings.getInt("selectedGroup", 0));
		} catch (ArrayIndexOutOfBoundsException e) {
			selectedGroup = mGroups.get(0);
		}
		if (groupSpinner != null) {
			groupSpinner.setText(selectedGroup.toString());
		}
		if (!isHolo) {
			LinearLayout newGameButton = (LinearLayout) findViewById(R.id.newGameButton);
			newGameButton.setOnClickListener(this);
			newGameButton
					.setVisibility(selectedGroup.getPlayers().size() < 2 ? View.INVISIBLE
							: View.VISIBLE);
		}
		sortedList = new ArrayList<Player>(selectedGroup.getPlayers());
		Collections.sort(sortedList, new RatingComparator<Player>());
		if (isHolo) {
			invalidateOptionsMenu();
		}

	}

	@Override
	public void onResume() {
		super.onResume();

	}

	public void removeGroup(int selection) {
		mGroups.remove(selection);
		if (mGroups.size() == 0) {
			mGroups.add(new Group("Default", true));
		}
		selectGroup(Math.max(0, selection - 1));
	}

	public void addGroup(Group group) {
		mGroups.add(group);
		groupChanged();
	}

	protected void groupChanged() {
		if (isHolo) {
			GroupsFragment groups = (GroupsFragment) getSupportFragmentManager()
					.findFragmentByTag("groups");
			if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
				groups.updateGroupSelection();
			} else {
				invalidateOptionsMenu();
			}

		}
		if (findViewById(R.id.groupSpinner) != null) {
			((Button) findViewById(R.id.groupSpinner)).setText(selectedGroup
					.toString());
		}
		itemsChanged();
		SharedPreferences.Editor edit = getPreferences(MODE_PRIVATE).edit();
		edit.putInt("selectedGroup", mGroups.indexOf(selectedGroup));
		edit.commit();
		save();
	}

	public void itemsChanged() {
		sortedList = new ArrayList<Player>(selectedGroup.getPlayers());
		Collections.sort(sortedList, !ratingSort ? new NameComparator<Player>(
				false) : new RatingComparator<Player>());
		if (isHolo) {
			invalidateOptionsMenu();
		} else {
			findViewById(R.id.newGameButton).setVisibility(
					selectedGroup.getPlayers().size() < 2 ? View.INVISIBLE
							: View.VISIBLE);
		}
		((BaseAdapter) ((PlayersFragment) getSupportFragmentManager()
				.findFragmentByTag("players")).getListAdapter())
				.notifyDataSetChanged();
		((BaseAdapter) ((GamesFragment) getSupportFragmentManager()
				.findFragmentByTag("games")).getListAdapter())
				.notifyDataSetChanged();
	}

	public void save() {
		Log.d(TAG, "Saving");
		Thread saverThread = new Thread(new Runnable() {
			@Override
			public void run() {
				SharedPreferences settings = getPreferences(MODE_PRIVATE);
				SharedPreferences.Editor edit = settings.edit();
				JSONArray jArray = new JSONArray();
				for (Group group : mGroups) {
					jArray.put(group.toJSON());
				}
				edit.putString("groups", jArray.toString());
				edit.commit();
				Log.d(TAG, jArray.toString());
			}
		});
		saverThread.run();
	}

	public Group getSelectedGroup() {
		return selectedGroup;
	}

	@Override
	public void onClick(View view) {
		switch (view.getId()) {
		case R.id.playerSortButton:
			ratingSort = !((ToggleButton) view).isChecked();
			itemsChanged();
			break;
		case R.id.newGameButton:
			Log.d(TAG, "newGameButton pressed");
			newGame();
			break;
		case R.id.addPlayerButton:
			newPlayer();
			break;
		case R.id.groupSpinner:
			Intent request = new Intent();
			request.putExtra(GroupActivity.GROUP_KEY, mGroups);
			request.putExtra(GroupActivity.SELECTION_KEY,
					getSelectedGroupPosition());
			request.setClass(this, GroupActivity.class);
			startActivityForResult(request, 1);
			break;
		default:
			throw new AssertionError("Undefined button catch");
		}
	}

	protected void addPlayer(String first, String last, int rating) {
		selectedGroup.addPlayer(new Player(first, last, rating));
		itemsChanged();
		save();
	}

	protected void playGame(Player winner, Player loser, boolean draw) {
		selectedGroup.playAGame(draw, winner, loser);
		itemsChanged();
		save();
	}

	@SuppressWarnings("unchecked")
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (resultCode == -1) {
			return;
		}
		Bundle extras = data.getExtras();
		mGroups = (ArrayList<Group>) extras.get(GroupActivity.GROUP_KEY);
		if (resultCode >= 0) {
			selectedGroup = mGroups.get(resultCode);
		}
		groupChanged();
	}

	public ArrayList<Player> getSortedList() {
		return sortedList;
	}

	@Override
	public void selectGroup(int position) {
		selectedGroup = mGroups.get(position);
		groupChanged();
	}

	@Override
	public ArrayList<Group> getGroupList() {
		return mGroups;
	}

	@Override
	public int getSelectedGroupPosition() {
		return mGroups.indexOf(selectedGroup);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		if (isHolo) {
			MenuInflater inflater = getMenuInflater();
			inflater.inflate(R.menu.main, menu);
			return true;
		}
		return false;
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		if (isHolo && menu.findItem(R.id.newGame) != null) {
			if (selectedGroup != null) {
				menu.findItem(R.id.newGame).setVisible(
						selectedGroup.getPlayers().size() >= 2);
			}
			menu.findItem(R.id.ratingSort).setChecked(ratingSort);
			return true;
		}
		return false;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.ratingSort:
			item.setChecked(!item.isChecked());
			ratingSort = item.isChecked();
			((PlayersFragment) getSupportFragmentManager().findFragmentByTag(
					"players")).clearSelection();
			((GamesFragment) getSupportFragmentManager().findFragmentByTag(
					"games")).setFilter(null);
			itemsChanged();
			return true;
		case R.id.newGame:
			newGame();
			return true;
		case R.id.newPlayer:
			newPlayer();
			return true;
		case android.R.id.home:
			((PlayersFragment) getSupportFragmentManager().findFragmentByTag(
					"players")).clearSelection();
			((GamesFragment) getSupportFragmentManager().findFragmentByTag(
					"games")).setFilter(null);
			return true;
		}
		return false;
	}

	private void newPlayer() {
		showDialog(R.id.dialog_new_player);
	}

	private Dialog newPlayerDialog() {
		Log.d(TAG, "addPlayerButton pressed");
		final Dialog playerDialog = new Dialog(this);
		playerDialog.setContentView(R.layout.new_player_layout);
		playerDialog.setTitle(R.string.newPlayer);

		final CheckBox ratingCheck = (CheckBox) playerDialog
				.findViewById(R.id.defaultRatingCheck);
		ratingCheck.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View paramView) {
				if (((CheckBox) paramView).isChecked()) {
					playerDialog.findViewById(R.id.ratingRow).setVisibility(
							View.GONE);
				} else {
					playerDialog.findViewById(R.id.ratingRow).setVisibility(
							View.VISIBLE);
				}
			}
		});

		Button playerOkButton = (Button) playerDialog
				.findViewById(R.id.playerOK);
		playerOkButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				String first = ((EditText) playerDialog
						.findViewById(R.id.firstNameInput)).getText()
						.toString();
				String last = ((EditText) playerDialog
						.findViewById(R.id.lastNameInput)).getText().toString();
				int rating;
				if (ratingCheck.isChecked()) {
					rating = 1300;
				} else {
					rating = Integer.valueOf(((EditText) playerDialog
							.findViewById(R.id.ratingInput)).getText()
							.toString());
				}
				addPlayer(first, last, rating);
				playerDialog.dismiss();
			}

		});
		Button playerCancelButton = (Button) playerDialog
				.findViewById(R.id.playerCancel);
		playerCancelButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				playerDialog.cancel();
			}
		});
		playerDialog.getWindow().setLayout(LayoutParams.FILL_PARENT,
				LayoutParams.WRAP_CONTENT);
		return playerDialog;
	}

	private void newGame() {
		showDialog(R.id.dialog_new_game);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private Dialog newGameDialog() {
		final Dialog dialog = new Dialog(this);
		dialog.setContentView(R.layout.new_game_dialog);
		dialog.setTitle(R.string.newGame);

		final AdapterView playerASpinner = (AdapterView) dialog
				.findViewById(R.id.playerASpinner);
		final AdapterView playerBSpinner = (AdapterView) dialog
				.findViewById(R.id.playerBSpinner);
		Adapter adapter;

		if (playerASpinner instanceof Spinner) {
			adapter = (playerASpinner instanceof Spinner) ? new PlayerNameAdapter<Player>(
					this, android.R.layout.simple_spinner_item,
					selectedGroup.getPlayers()) : null;
			((ArrayAdapter<Player>) adapter)
					.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		} else {
			adapter = new PlayerAdapter(this);
			((AbsListView) playerASpinner)
					.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
			((AbsListView) playerBSpinner)
					.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

		}

		playerASpinner.setAdapter(adapter);
		playerBSpinner.setAdapter(adapter);

		playerASpinner.setSelection(0);
		playerBSpinner.setSelection(1);

		if (!(playerASpinner instanceof Spinner)) {
			((AbsListView) playerASpinner).setItemChecked(0, true);
			((AbsListView) playerBSpinner).setItemChecked(1, true);
		}

		final RadioGroup radios = (RadioGroup) dialog
				.findViewById(R.id.winnerGroup);
		radios.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(RadioGroup paramRadioGroup,
					int paramInt) {
				setButtonEnabled(dialog, playerASpinner, playerBSpinner, radios);
			}
		});

		if (playerASpinner instanceof Spinner) {
			playerASpinner
					.setOnItemSelectedListener(new OnItemSelectedListener() {

						@Override
						public void onItemSelected(AdapterView<?> arg0,
								View arg1, int arg2, long arg3) {
							setButtonEnabled(dialog, playerASpinner,
									playerBSpinner, radios);
						}

						@Override
						public void onNothingSelected(AdapterView<?> arg0) {
						}

					});
		} else {
			playerASpinner.setOnItemClickListener(new OnItemClickListener() {

				@Override
				public void onItemClick(AdapterView<?> paramAdapterView,
						View paramView, int paramInt, long paramLong) {
					playerBSpinner.setSelection(paramInt);
					((AbsListView) paramAdapterView).setItemChecked(paramInt,
							true);
					setButtonEnabled(dialog, playerASpinner, playerBSpinner,
							radios);
				}
			});
		}
		if (playerBSpinner instanceof Spinner) {
			playerBSpinner
					.setOnItemSelectedListener(new OnItemSelectedListener() {

						@Override
						public void onItemSelected(AdapterView<?> arg0,
								View arg1, int arg2, long arg3) {
							setButtonEnabled(dialog, playerASpinner,
									playerBSpinner, radios);
						}

						@Override
						public void onNothingSelected(AdapterView<?> arg0) {
						}

					});
		} else {
			playerBSpinner.setOnItemClickListener(new OnItemClickListener() {

				@Override
				public void onItemClick(AdapterView<?> paramAdapterView,
						View paramView, int paramInt, long paramLong) {
					playerBSpinner.setSelection(paramInt);
					setButtonEnabled(dialog, playerASpinner, playerBSpinner,
							radios);
				}
			});
		}

		Button okButton = (Button) dialog.findViewById(R.id.gameOkButton);
		okButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				Player winner, loser;
				if (radios.getCheckedRadioButtonId() == R.id.playerBWinButton) {
					winner = getSelectedPlayer(playerBSpinner);
					loser = getSelectedPlayer(playerASpinner);
				} else {
					winner = getSelectedPlayer(playerASpinner);
					loser = getSelectedPlayer(playerBSpinner);
				}
				playGame(winner, loser,
						radios.getCheckedRadioButtonId() == R.id.drawButton);
				Log.d(TAG, "isDraw = "
						+ (radios.getCheckedRadioButtonId() == R.id.drawButton));
				dialog.dismiss();
			}

			private Player getSelectedPlayer(AdapterView view) {
				if (view instanceof Spinner) {
					return (Player) view.getSelectedItem();
				}
				int selected = ((AbsListView) view).getCheckedItemPosition();
				return (Player) view.getItemAtPosition(selected);
			}

		});
		Button cancelButton = (Button) dialog
				.findViewById(R.id.gameCancelButton);
		cancelButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				dialog.cancel();
			}
		});
		dialog.getWindow().setLayout(LayoutParams.FILL_PARENT,
				LayoutParams.WRAP_CONTENT);
		return dialog;
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case R.id.dialog_new_game:
			return newGameDialog();
		case R.id.dialog_new_player:
			return newPlayerDialog();
		}
		return null;
	}

	@SuppressWarnings("rawtypes")
	public static void setButtonEnabled(Dialog dialog,
			AdapterView playerASpinner, AdapterView playerBSpinner,
			RadioGroup radios) {
		Button button = (Button) dialog.findViewById(R.id.gameOkButton);
		if (playerASpinner instanceof Spinner) {
			button.setEnabled(playerASpinner.getSelectedItemPosition() != playerBSpinner
					.getSelectedItemPosition()
					&& radios.getCheckedRadioButtonId() != -1);
		} else {
			button.setEnabled(((AbsListView) playerASpinner)
					.getCheckedItemPosition() != ((AbsListView) playerBSpinner)
					.getCheckedItemPosition()
					&& radios.getCheckedRadioButtonId() != -1);
		}
	}
}